<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>[3.6]-扩展类库：新型计划任务 | PhalApi(π框架) - PHP轻量级开源接口框架 - 助你创造价值！</title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <meta content="telephone=no" name="format-detection">
    <meta content="email=no" name="format-detection">
    <meta name="Author" content="PhalApi,ecitlm,dogstar">
    <meta name="description" content="[3.6]-扩展类库：新型计划任务，PhalApi是一个PHP轻量级开源接口框架，致力于快速开发接口服务。支持HTTP/SOAP/RPC等协议，可用于搭建接口/微服务/RESTful接口/Web Services。我们不断更新，保持生气；为接口负责，为开源负责！并承诺永久免费！">
    <meta name="keywords" content="PhalApi,phalapi,phalapi接口开发,后台接口开发,后台接口开发框架,接口开发,接口框架,开源接口框架,PHP后台接口开发,PHP接口开发,PHP接口框架,PHP后台接口框架,phalapi官网,PHP接口框架,php接口开发框架,php接口开发,php web框架,π框架,π开发框架,π接口框架,π接口开发框架,api接口,php接口,,PHP接口框架,phalapi文档,phalapi wiki,PhalApi文档,phalapi在线文档,phalapi官方文档">

    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" media="screen">
    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css" media="screen">
    <link rel="stylesheet" href="../css/main.css" />
    <link rel="stylesheet" href="../css/loading_bar.css" />
    <link rel="icon" href="http://webtools.qiniudn.com/dog_catch.png" type="image/x-icon" />
    <script src="../js/pace.min.js"></script>
	
	<!-- 代码高亮 -->
	<link rel="stylesheet" href="../css/highlight.min.css">
	<script src="../js/highlight.min.js"></script>
	<script>hljs.initHighlightingOnLoad();</script>
    
</head>

<body>
    <!-- navbar start -->
    <div class="navbar navbar-default navbar-fixed-top" id="mainnav" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand website_name" href="/"><!-- <span>PhalApi</span> --><strong>PhalApi</strong></a>
            </div>
            <div class="navbar-collapse collapse" aria-expanded="false" style="height: 1px;">
                <ul class="nav navbar-nav navbar-right" id="nav_bar">
                    <li><a href="/"><span class="glyphicon glyphicon-home"></span></a></li>
                    <li><a href="http://qa.phalapi.net/">社区</a></li>
                    <li><a href="/download.html">下载</a></li>
                    <li class="active"><a href="/wikis/">文档</a></li>
                    <li><a href="http://www.ituring.com.cn/book/2405">书籍</a></li>
                    <li><a href="http://demo.phalapi.net/">体验</a></li>
                    <li><a href="/about.html">关于</a></li>
                    <li><a href="/donate.html">贡献</a></li>
                    <li><a href="/wikis/en/">English</a></li>
                </ul>
            </div>
            <!--/.nav-collapse -->
        </div>
    </div>
    <!-- navbar end -->


    <div id="content">
        <div class="container">
            <div class="row row-md-flex row-md-flex-wrap">
                <h4><a href="/wikis/%5B3.5%5D-%E6%89%A9%E5%B1%95%E7%B1%BB%E5%BA%93%EF%BC%9A%E4%B8%83%E7%89%9B%E4%BA%91%E5%AD%98%E5%82%A8%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="#">下一章</a></h4>
<hr />
<h2>3.6.1 扩展类库：新型计划任务</h2>
<p>此扩展类型用于后台计划任务的调度，主要功能点有：</p>
<ul>
<li>1、提供了Redis/文件/数据库三种MQ队列</li>
<li>2、提供了本地和远程两种调度方式</li>
<li>3、以接口的形式实现计划任务</li>
<li>4、提供统一的crontab调度</li>
</ul>
<p>更多内容，请查看：<a href="/wikis/%5B1.31%5D-%E6%96%B0%E5%9E%8B%E8%AE%A1%E5%88%92%E4%BB%BB%E5%8A%A1%EF%BC%9A%E4%BB%A5%E6%8E%A5%E5%8F%A3%E5%BD%A2%E5%BC%8F%E5%AE%9E%E7%8E%B0%E7%9A%84%E8%AE%A1%E5%88%92%E4%BB%BB%E5%8A%A1.html">[1.31] 新型计划任务：以接口形式实现的计划任务</a>  </p>
<h2>3.6.2 安装</h2>
<h3>(1)内置扩展包</h3>
<p>此安装略，已内置于PhalApi框架中。</p>
<blockquote>
<p>温馨提示：<br />
PhalApi需要PhaApi 1.2.0及以上版本。</p>
</blockquote>
<h3>(2)配置</h3>
<p>我们需要在 <strong>./Config/app.php</strong> 配置文件中追加以下配置：</p>
<pre><code class="language-php">    /**
     * 计划任务配置
     */
    'Task' =&gt; array(
        //MQ队列设置，可根据使用需要配置
        'mq' =&gt; array(
            'file' =&gt; array(
                'path' =&gt; API_ROOT . '/Runtime',
                'prefix' =&gt; 'phalapi_task',
            ),
            'redis' =&gt; array(
                'host' =&gt; '127.0.0.1',
                'port' =&gt; 6379,
                'prefix' =&gt; 'phalapi_task',
                'auth' =&gt; '',
            ),
            'mc' =&gt; array(
                'host' =&gt; '127.0.0.1',
                'port' =&gt; 11211,
            ),
        ),

        //Runner设置，如果使用远程调度方式，请加此配置
        'runner' =&gt; array(
            'remote' =&gt; array(
                'host' =&gt; 'http://library.phalapi.net/demo/',
                'timeoutMS' =&gt; 3000,
            ),
        ),
    ),</code></pre>
<p>以上内容看情况需要而配置。  </p>
<h3>(3)数据库表</h3>
<p>当需要使用数据库MQ列队时，还需要将以下数据库的配置追加到 <strong>./Config/dbs.php</strong> 中：</p>
<pre><code class="language-php">    'tables' =&gt; array(

    //请将以下配置拷贝到 ./Config/dbs.php 文件对应的位置中，未配置的表将使用默认路由

        //10张表，可根据需要，自行调整表前缀、主键名和路由
        'task_mq' =&gt; array(
            'prefix' =&gt; 'phalapi_',
            'key' =&gt; 'id',
            'map' =&gt; array(
                array('db' =&gt; 'db_demo'),
                array('start' =&gt; 0, 'end' =&gt; 9, 'db' =&gt; 'db_demo'),
            ),
        ),
    )</code></pre>
<p>同时，需要将 ./Data/phalapi_task_mq.sql 文件的SQL建表语句导入到你的数据库。你也可以将利用脚本来生成。</p>
<h2>3.6.3 入门使用</h2>
<h3>(1)加入MQ队列</h3>
<p>首先，我们需要在入口文件进行对Task的初始化：</p>
<pre><code class="language-php">DI()-&gt;loader-&gt;addDirs('Library');
$mq = new Task_MQ_Redis();  //可以选择你需要的MQ
DI()-&gt;taskLite = new Task_Lite($mq);</code></pre>
<p>然后，这样即可添加一个新的计划任务到MQ：</p>
<pre><code class="language-php">DI()-&gt;taskLite-&gt;add('Task.DoSth', array('id' =&gt; 1));</code></pre>
<h3>(2)计划任务的启动</h3>
<p>在启动计划任务前，我们需要编写简单的脚本，一如这样：</p>
<pre><code class="language-php">#!/usr/bin/env php
&lt;?php
require_once '/path/to/Public/init.php';

DI()-&gt;loader-&gt;addDirs('Demo');

if ($argc &lt; 2) {
    echo "Usage: $argv[0] &lt;service&gt; \n\n";
    exit(1);
}

$service = trim($argv[1]);

$mq = new Task_MQ_Redis();
$runner = new Task_Runner_Local($mq);
$rs = $runner-&gt;go($service);

echo "\nDone:\n", json_encode($rs), "\n\n";</code></pre>
<p>然后使用nohup或者crontab启动即可。  </p>
<h3>(3)续篇 - 统一的crontab计划任务</h3>
<p>上面第二点的启动是通用、自定义、也是自由的启动方式。  </p>
<p>这里再提供一种具体的、统一的启动方式，即使用crontab的方式。  </p>
<p>首先，创建以下表(或见./Library/Task/Data/phalapi_task_progress.sql文件)：</p>
<pre><code class="language-sql">CREATE TABLE `phalapi_task_progress` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `title` varchar(200) DEFAULT '' COMMENT '任务标题',
      `trigger_class` varchar(50) DEFAULT '' COMMENT '触发器类名',
      `fire_params` varchar(255) DEFAULT '' COMMENT '需要传递的参数，格式自定',
      `interval_time` int(11) DEFAULT '0' COMMENT '执行间隔，单位：秒',
      `enable` tinyint(1) DEFAULT '1' COMMENT '是否启动，1启动，0禁止',
      `result` varchar(255) DEFAULT '' COMMENT '运行的结果，以json格式保存',
      `state` tinyint(1) DEFAULT '0' COMMENT '进程状态，0空闲，1运行中，-1异常退出',
      `last_fire_time` int(11) DEFAULT '0' COMMENT '上一次运行时间',
      PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;</code></pre>
<p>接着，添加crontab计划任务：</p>
<pre><code class="language-bash">$ crontab -e

*/1 * * * * /usr/bin/php /path/to/PhalApi/Library/Task/crontab.php &gt;&gt; /tmp/phalapi_task_crontab.log 2&gt;&amp;1
</code></pre>
<p>然后，实现你的计划任务服务接口：</p>
<pre><code class="language-php">&lt;?php
class Api_Task extends PhalApi_Api {

      public function doSth() {
            // ...
      }
}</code></pre>
<p>最后，配置计划任务：</p>
<pre><code class="language-sql">INSERT INTO `phalapi_task_progress`(title, trigger_class, fire_params, interval_time)  VALUES('你的任务名字', 'Task_Progress_Trigger_Common', 'Task_Demo.DoSth&amp;Task_MQ_File&amp;Task_Runner_Local', '300');</code></pre>
<p>注意，在配置时，需要指明MQ和Runner的类型。</p>
<h2>3.6.4 更多说明</h2>
<h3>(1)依赖的资源服务</h3>
<table class="table table-bordered">
<thead>
<tr>
<th>名称</th>
<th>类</th>
<th>没有时是否自动创建</th>
</tr>
</thead>
<tbody>
<tr>
<td>curl</td>
<td>PhalApi_CUrl</td>
<td>是</td>
</tr>
<tr>
<td>request</td>
<td>PhalApi_Request</td>
<td>强制每次初始化，用于本地调度时</td>
</tr>
<tr>
<td>response</td>
<td>PhalApi_Response_Json</td>
<td>强制每次初始化，用于本地调度时</td>
</tr>
</tbody>
</table>
<h3>(2)MQ</h3>
<h4>Redis MQ队列</h4>
<p>Redis MQ队列需要的配置为：</p>
<pre><code class="language-php">    'Task' =&gt; array(
        //MQ队列设置，可根据使用需要配置
        'mq' =&gt; array(
            'redis' =&gt; array(
                'host' =&gt; '127.0.0.1',
                'port' =&gt; 6379,
                'prefix' =&gt; 'phalapi_task',
                'auth' =&gt; '',
            ),
        ),
    ),</code></pre>
<p>其中：  </p>
<table class="table table-bordered">
<thead>
<tr>
<th>选项</th>
<th>是否必须</th>
<th>默认值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>host</td>
<td>否</td>
<td>127.0.0.1</td>
<td>redis的HOST</td>
</tr>
<tr>
<td>port</td>
<td>否</td>
<td>6379</td>
<td>redis的端口</td>
</tr>
<tr>
<td>prefix</td>
<td>否</td>
<td>phalapi_task</td>
<td>key的前缀</td>
</tr>
<tr>
<td>auth</td>
<td>否</td>
<td>redis的验证，不为空时执行验证</td>
</tr>
</tbody>
</table>
<p>可以这样创建Redis MQ队列：</p>
<pre><code class="language-php">//方法一：使用app.Task.mq.redis配置
$mq = new Task_MQ_Redis();

//方法二：外部依赖注入
$redisCache = new PhalApi_Cache_Redis(array('host' =&gt; '127.0.0.1'));
$mq = new Task_MQ_Redis($redisCache);</code></pre>
<h4>文件MQ队列（通常不能共享，队列大小不限制，有效期一年）</h4>
<p>文件MQ需要的配置为：</p>
<pre><code class="language-php">    'Task' =&gt; array(
        //MQ队列设置，可根据使用需要配置
        'mq' =&gt; array(
            'file' =&gt; array(
                'path' =&gt; API_ROOT . '/Runtime',
                'prefix' =&gt; 'phalapi_task',
            ),
        ),
    ),</code></pre>
<p>其中：  </p>
<table class="table table-bordered">
<thead>
<tr>
<th>选项</th>
<th>是否必须</th>
<th>默认值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>path</td>
<td>否</td>
<td>API_ROOT/Runtime</td>
<td>缓存的文件目录</td>
</tr>
<tr>
<td>prefix</td>
<td>否</td>
<td>phalapi_task</td>
<td>key的前缀</td>
</tr>
</tbody>
</table>
<p>可以这样创建文件MQ队列：</p>
<pre><code class="language-php">//方法一：使用app.Task.mq.file配置
$mq = new Task_MQ_File();

//方法二：外部依赖注入
$fileCache = new PhalApi_Cache_File(array('path' =&gt; '/tmp/cache'));
$mq = new Task_MQ_File($fileCache);</code></pre>
<h4>Memcached/Memcache MQ队列（通常队列大小不能超过1M，有效期29天）</h4>
<p>MC MQ需要的配置为：</p>
<pre><code class="language-php">    'Task' =&gt; array(
        //MQ队列设置，可根据使用需要配置
        'mq' =&gt; array(
            'mc' =&gt; array(
                'host' =&gt; '127.0.0.1',
                'port' =&gt; 11211,
            ),
        ),
    ),</code></pre>
<p>其中：  </p>
<table class="table table-bordered">
<thead>
<tr>
<th>选项</th>
<th>是否必须</th>
<th>默认值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>host</td>
<td>否</td>
<td>127.0.0.1</td>
<td>MC的host</td>
</tr>
<tr>
<td>port</td>
<td>否</td>
<td>11211</td>
<td>MC端口</td>
</tr>
</tbody>
</table>
<p>可以这样创建文件MQ队列：</p>
<pre><code class="language-php">//方法一：使用app.Task.mq.mc配置
$mq = new Task_MQ_Memcached();

//方法二：外部依赖注入
$mc = new PhalApi_Cache_Memcached(array('host' =&gt; '127.0.0.1', 'port' =&gt; 11211));
$mq = new Task_MQ_File($mc);</code></pre>
<h4>数据库MQ队列</h4>
<p>数据库MQ队列需要的配置为：</p>
<pre><code class="language-php">    'tables' =&gt; array(

        //请将以下配置拷贝到 ./Config/dbs.php 文件对应的位置中，未配置的表将使用默认路由

        //10张表，可根据需要，自行调整表前缀、主键名和路由
        'task_mq' =&gt; array(
            'prefix' =&gt; 'phalapi_',
            'key' =&gt; 'id',
            'map' =&gt; array(
                array('db' =&gt; 'db_demo'),
                array('start' =&gt; 0, 'end' =&gt; 9, 'db' =&gt; 'db_demo'),
            ),
        ),
    )</code></pre>
<p>可以这样创建数据库MQ队列：</p>
<pre><code class="language-php">$mq = new Task_MQ_DB();</code></pre>
<h4>数组MQ队列</h4>
<p>数组MQ队列是将MQ存放在PHP的数组里面，用于单元测试或者是一次性、临时性的计划任务调度。</p>
<p>可以这样创建数据库MQ队列：</p>
<pre><code class="language-php">$mq = new Task_MQ_Array();</code></pre>
<h3>(3)本地和远程调度</h3>
<h4>本地调度的创建</h4>
<pre><code class="language-php">$runner = new Task_Runner_Local($mq, 10);  //10表示每批次弹出10个进行处理</code></pre>
<p>需要注意的是，每次执行一个计划任务，都会重新初始化必要的DI资源服务。<br />
且此调度方式不能用于接口请求时的同步调用。  </p>
<h4>远程调度的创建</h4>
<p>首先需要以下配置：</p>
<pre><code class="language-php">    /**
     * 计划任务配置
     */
    'Task' =&gt; array(
        //Runner设置，如果使用远程调度方式，请加此配置
        'runner' =&gt; array(
            'remote' =&gt; array(
                'host' =&gt; 'http://library.phalapi.net/demo/',
                'timeoutMS' =&gt; 3000,
            ),
        ),
    ),</code></pre>
<p>其中：  </p>
<table class="table table-bordered">
<thead>
<tr>
<th>选项</th>
<th>是否必须</th>
<th>默认值</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>host</td>
<td>是</td>
<td>接口域名链接</td>
</tr>
<tr>
<td>timeoutMS</td>
<td>否</td>
<td>3000</td>
<td>接口超时时间，单位毫秒</td>
</tr>
</tbody>
</table>
<p>可以这样创建：</p>
<pre><code class="language-php">//使用默认的连接器 - HTTP + POST的方式
$runner = new Task_Runner_Remote($mq, 10); //10表示每批次弹出10个进行处理

//或者，指定连接器
$connector = new Task_Runner_Remote_Connector_Impl();
$runner = new Task_Runner_Remote($mq, 10, $connector); //10表示每批次弹出10个进行处理</code></pre>
<hr />
<h4><a href="/wikis/%5B3.5%5D-%E6%89%A9%E5%B1%95%E7%B1%BB%E5%BA%93%EF%BC%9A%E4%B8%83%E7%89%9B%E4%BA%91%E5%AD%98%E5%82%A8%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="#">下一章</a></h4><div style="float: left">
<h4>
<a href="http://qa.phalapi.net/">还有疑问？欢迎到社区提问！</a>
</h4>
</div>
            </div>
        </div>
    </div>

 <!-- 广告位 -->
<div class="grid-wrapper desktop-only">
	<p align="center">
		<a href="http://7xiz2f.com1.z0.glb.clouddn.com/%E6%88%91%E7%9A%84%E5%90%8D%E5%AD%97%E5%8F%AB%EF%BC%9A%CF%80%E6%A1%86%E6%9E%B6%20-%20PhalApi%202016%E5%B9%B4%E5%BA%A6%E5%BC%80%E6%BA%90%E6%80%BB%E7%BB%93%20-%20%E5%AE%98%E6%96%B9%E5%87%BA%E5%93%81.pdf" target="blank"><img width="950" height="100" src="http://7xiz2f.com1.z0.glb.clouddn.com/ad_20170104.png"></a>
		<a href="http://www.itran.cc/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/9/69/b88bc92455dc1239f9a5bf8d72929.png"></a>
		<a href="http://web-tools.phalapi.net/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/7/d0/88f523566c482296aecc43d185ca2.png"></a>
	</p>
</div>

        <!-- footer -->
        <div class="footer">
            <div class="link container ">
                <div class=" col-xs-7 col-sm-7 col-md-7 col-lg-7 ">
                    <h3>PhalApi (π框架)</h3>
                    <p>一个轻量级PHP开源接口框架，专注于接口服务开发，支持HTTP/SOAP/RPC协议，拥有自动生成的在线文档、多种开发语言的客户端SDK包以及可重用的扩展类库，可用于快速搭建微服务、RESTful接口或Web
                        Services。</p>
                    <!-- <p>:</p> -->
                    <span>友情链接:</span>
                    <a href="https://www.phalapi.net/" target="_blank"> PhalApi </a>
                    <a href="http://www.oschina.net/" target="_blank"> 开源中国 </a>
                    <a href="https://www.itran.cc/" target="_blank">艾翻译</a>
                    <a href="http://www.phalconphp.com/en/" target="_blank">Phalcon</a>
                    <a href="https://phpunit.de/manual/3.7/zh_cn/automating-tests.html" target="_blank">PHPUnit</a>
                    <a href="http://www.thoughtworks.com/cn/" target="_blank">ThoughtWorks</a>
                    <a href="mailto:chanzonghuang@gmail.com">友链交换</a>

                </div>
                <div class=" col-xs-5 col-sm-5 col-md-5 col-lg-5 contact_us ">
                    <h3>联系我们</h3>
                    <a href="https://github.com/phalapi/phalapi"><img src="../images/github.png" alt="github" /></a>
                    <a href="http://weibo.com/p/100808d236e99beb645bfb56ed1c37dde9b8bd?k=phalapi%E5%BC%80%E6%BA%90%E6%A1%86%E6%9E%B6&from=501&_from_=huati_topic"><img src="../images/weibo.png"  alt="weibo" /></a>
                    <a href="http://7xslqv.com1.z0.glb.clouddn.com/images/1/b0/894fde762850cb11250253f7d5ede.png"><img src="../images/zfb.png"  alt="zfb" /></a>
                    <a href="https://jq.qq.com/?_wv=1027&k=4A6reum"><img src="../images/qq.png"  alt="qq" /></a>
					<a href="http://git.oschina.net/dogstar/PhalApi"><img src="../images/git-oschina.png"  alt="git-oschina" /></a>
                </div>
                <div class="cls"></div>
                <div class="text-center copy_right"> ©2015-2017 PhalApi All Rights Reserved. <a href="http://www.miitbeian.gov.cn" target="_blank">粤ICP备15028808号</a>

				<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1255326144'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1255326144%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
                </div>
            </div>
        </div>
    </div>


    <a href="https://github.com/phalapi"><img id="gitHub_fllow" style="position: fixed; top: 0; right: 0; border: 0;z-index:9999" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a>


    <script src="../js/jquery-1.11.1.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
</body>

</html>